﻿using System;
using System.ComponentModel;
using System.Windows.Forms;
namespace DA6502
{

    public partial class FrmEntries : Form
    {
        #region ==============================| 类属性 |==============================

        private FrmMain parent;

        #endregion

        #region ==============================| 委托与事件 |==============================

        public delegate void ReverseSingleHandler(ushort ad);
        public delegate void ReverseMultiHandler(ushort ad);

        public bool Dirty = false;

        /// <summary>
        /// 反汇编单行事件
        /// </summary>
        public event ReverseSingleHandler ReverseSingle;

        /// <summary>
        /// 反汇编多行事件
        /// </summary>
        public event ReverseMultiHandler ReverseMulti;
        #endregion

        #region ==============================| 类方法 |==============================

        public FrmEntries(FrmMain frm)
        {
            InitializeComponent();
            parent = frm;
        }

        #endregion

        #region ==============================| 列表相关 |==============================

        /// <summary>
        /// 列表中是否已经包含某个入口地址
        /// </summary>
        /// <param name="ad">入口地址</param>
        /// <returns>true:已经包含<br></br>false:未包含</returns>
        public bool IsContainsAddress(ushort ad)
        {
            bool r = false;
            for (int i = 0; i < lsvEntries.Items.Count; i++)
                if (r = lsvEntries.Items[i].Text.Equals(ad.ToString("X4")))
                    break;
            return r;
        }

        /// <summary>
        /// 列表中是否已经包含某个标签
        /// </summary>
        /// <param name="label">标签</param>
        /// <returns>true:已经包含<br></br>false:未包含</returns>
        public bool ContainsLabel(string label)
        {
            bool r = false;
            for (int i = 0; i < lsvEntries.Items.Count; i++)
                if (r = lsvEntries.Items[i].SubItems[0].Text.Equals(label))
                    break;
            return r;
        }

        /// <summary>
        /// 向列表中添加一个入口地址并设置标签
        /// </summary>
        /// <param name="ad">入口地址</param>
        /// <param name="label">标签</param>
        public void SetEntry(ushort ad, string label)
        {
            bool labelExist = false;
            for (int i = 0; i < lsvEntries.Items.Count; i++)
            {
                if (lsvEntries.Items[i].SubItems[0].Text.Equals(ad.ToString("X4")))
                {
                    labelExist = true;
                    lsvEntries.Items[i].SubItems[1].Text = label;
                }
            }
            if (!labelExist)
            {
                ListViewItem lvi = new ListViewItem(ad.ToString("X4"));
                lvi.SubItems.Add(label);
                lsvEntries.Items.Add(lvi);
            }
            Dirty = true;
        }

        /// <summary>
        /// 向列表中添加一个入口地址
        /// </summary>
        /// <param name="ad">入口地址</param>
        public void SetEntry(ushort ad)
        {
            SetEntry(ad, String.Empty);
        }

        /// <summary>
        /// 从列表中删除一个入口地址
        /// </summary>
        /// <param name="ad">入口地址</param>
        public void RemoveEntry(ushort ad)
        {
            for (int i = 0; i < lsvEntries.Items.Count; i++)
            {
                if (lsvEntries.Items[i].Text.Equals(ad.ToString("X4")))
                {
                    lsvEntries.Items.RemoveAt(i);
                    break;
                }
            }
            Dirty = true;
        }

        public ListView GetListView() => lsvEntries;

        public void Clear()
        {
            lsvEntries.Clear();
            Dirty = false;
        }
        #endregion

        #region ==============================| 用户事件回调 |==============================

        /// <summary>
        /// 右键菜单 - 反汇编单行 点击事件
        /// </summary>
        private void ReverseSingle_Click(object sender, EventArgs e)
        {
            ushort ad;
            ListViewItem lsi = lsvEntries.FocusedItem;
            ad = Convert.ToUInt16(lsi.Text, 16);

            //  Fire Event
            ReverseSingle?.Invoke(ad);
        }

        /// <summary>
        /// 右键菜单 - 反汇编多行 点击事件
        /// </summary>
        private void ReverseMulti_Click(object sender, EventArgs e)
        {
            ushort ad;
            ListViewItem lsi = lsvEntries.FocusedItem;
            ad = Convert.ToUInt16(lsi.Text, 16);

            //  Fire Event
            ReverseMulti?.Invoke(ad);
        }

        /// <summary>
        /// 右键菜单弹出事件<br></br>
        /// 若列表为空，则取消弹出
        /// </summary>
        public void Ctm_Opening(object sender, CancelEventArgs e)
        {
            e.Cancel = lsvEntries.Items.Count == 0;
            if (!e.Cancel)
            {
                ListViewItem lsi = lsvEntries.FocusedItem;
                lsi.Selected = true;
                txtLabel.Text = lsi.SubItems.Count == 0 ? String.Empty : lsi.SubItems[1].Text;
            }
        }

        /// <summary>
        /// 右键菜单 - 标签名称 改变事件
        /// </summary>
        private void TxtLabel_Changed(object sender, EventArgs e)
        {
            ListViewItem lsi = lsvEntries.FocusedItem;
            if (lsi.SubItems.Count == 0)
            {
                lsi.SubItems.Add(txtLabel.Text);
            }
            else
            {
                lsi.SubItems[1].Text = txtLabel.Text;
            }
            Dirty = true;
        }

        /// <summary>
        /// 入口列表窗体可见性改变事件<br></br>
        /// 根据入口列表窗体是否可见，设置主窗体菜单中 窗口 - 子程序入口列表 前的对号。
        /// </summary>
        private void OnVisibleChanged(object sender, EventArgs e)
        {
            parent.mnuEntries.Checked = Visible;
        }

        /// <summary>
        /// 入口列表窗体关闭事件<br></br>
        /// 入口列表窗体不可通过点击X关闭（资源不可释放），只能隐藏显示
        /// </summary>
        private void OnClose(object sender, FormClosingEventArgs e)
        {
            e.Cancel = true;
            Hide();
        }

        /// <summary>
        /// 列表条项双击事件
        /// </summary>
        private void JumpTo_Click(object sender, EventArgs e)
        {
            ushort row = Convert.ToUInt16(lsvEntries.FocusedItem.Text, 16);
            parent.JumpTo(row);
        }
        #endregion
    }
}
